--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
meshchatx/src/backend/sticker_utils.py fa46dc4ce9ab50cbe66a7a9e4b3bca0140102345 (fa46dc4c) Text, 24.18 KB
T8b949e# SPDX-License-Identifier: 0BSD
T8b949e"""Validation, hashing, and metadata extraction for user sticker payloads.
MeshChatX aligns with the Telegram sticker specification while keeping the
historical "saved image" formats supported as a separate legacy class so
existing libraries continue to work after migration.
Sticker classes:
static
PNG or WebP. Telegram-strict: max 512 KB, max 512x512 px and at least one
side must be exactly 512 px.
animated
TGS (gzipped Lottie JSON). Telegram-strict: max 64 KB, canvas 512x512,
30-60 FPS, max 3 s, looped (loop attribute is informational only).
video
WebM/VP9 with no audio. Telegram-strict: max 256 KB, max 512x512 with at
least one side exactly 512 px, max 30 FPS, max 3 s.
legacy
PNG/JPEG/GIF/WebP/BMP without dimension/duration enforcement. Capped at
512 KB. Used for the historical free-form sticker library and for save
images coming from chats. Not exportable as part of a Telegram-style pack.
"""
Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations
Tff7b72import T7ee787base64
Tff7b72import T7ee787gzip
Tff7b72import T7ee787hashlib
Tff7b72import T7ee787json
Tff7b72import T7ee787struct
Tff7b72import T7ee787zlib
T8b949e# Telegram-aligned size limits.
Te6edf3MAX_STATIC_BYTES Tff7b72= T79c0ff512 Tff7b72* T79c0ff1024
Te6edf3MAX_ANIMATED_BYTES Tff7b72= T79c0ff64 Tff7b72* T79c0ff1024
Te6edf3MAX_VIDEO_BYTES Tff7b72= T79c0ff256 Tff7b72* T79c0ff1024
T8b949e# Backwards-compatible alias used by the legacy upload path.
Te6edf3MAX_STICKER_BYTES Tff7b72= Te6edf3MAX_STATIC_BYTES
Te6edf3MAX_STICKERS_PER_IDENTITY Tff7b72= T79c0ff2000
Te6edf3MAX_STICKER_PACKS_PER_IDENTITY Tff7b72= T79c0ff200
Te6edf3MAX_STICKERS_PER_PACK Tff7b72= T79c0ff120
Te6edf3STICKER_CANVAS Tff7b72= T79c0ff512
Te6edf3ANIMATED_FPS_MIN Tff7b72= T79c0ff30
Te6edf3ANIMATED_FPS_MAX Tff7b72= T79c0ff60
Te6edf3VIDEO_FPS_MAX Tff7b72= T79c0ff30
Te6edf3MAX_DURATION_MS Tff7b72= T79c0ff3000
Te6edf3_LEGACY_TYPES Tff7b72= Tffa657frozensetTb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ffpngTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffjpegTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffjpgTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffgifTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffwebpTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffbmpTa5d6ff"Tb4b4b4}Tb4b4b4)
Te6edf3_TELEGRAM_STATIC_TYPES Tff7b72= Tffa657frozensetTb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ffpngTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffwebpTa5d6ff"Tb4b4b4}Tb4b4b4)
Te6edf3_ALLOWED_TYPES Tff7b72= Tffa657frozensetTb4b4b4(
Te6edf3_LEGACY_TYPES Tff7b72| Tb4b4b4{Ta5d6ff"Ta5d6fftgsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffwebmTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3_TYPE_ALIASES Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffjpegTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffjpegTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffjpgTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffjpegTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffpjpegTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffjpegTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffpngTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffpngTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffgifTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffgifTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffwebpTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffwebpTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffbmpTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffbmpTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fftgsTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fftgsTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffwebmTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffwebmTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffx-tgstickerTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fftgsTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fftgstickerTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fftgsTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffvideo/webmTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffwebmTa5d6ff"Tb4b4b4,
Tb4b4b4}
Tff7b72def Td2a8ffnormalize_image_typeTb4b4b4(Te6edf3image_typeTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tffa657str Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Map a user-supplied MIME or extension to a normalized sticker type key."""
Tff7b72if Tff7b72not Te6edf3image_typeTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3t Tff7b72= Tffa657strTb4b4b4(Te6edf3image_typeTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Te6edf3t Tff7b72= Te6edf3tTff7b72.Td2a8ffremoveprefixTb4b4b4(Ta5d6ff"Ta5d6ffimage/Ta5d6ff"Tb4b4b4)
Te6edf3t Tff7b72= Te6edf3tTff7b72.Td2a8ffremoveprefixTb4b4b4(Ta5d6ff"Ta5d6ffvideo/Ta5d6ff"Tb4b4b4)
Te6edf3t Tff7b72= Te6edf3tTff7b72.Td2a8ffremoveprefixTb4b4b4(Ta5d6ff"Ta5d6ffapplication/Ta5d6ff"Tb4b4b4)
Te6edf3t Tff7b72= Te6edf3_TYPE_ALIASESTff7b72.Td2a8ffgetTb4b4b4(Te6edf3tTb4b4b4, Te6edf3tTb4b4b4)
Tff7b72return Te6edf3t Tff7b72if Te6edf3t Tff7b72in Te6edf3_ALLOWED_TYPES Tff7b72else Tff7b72None
Tff7b72def Td2a8ffcontent_hash_hexTb4b4b4(Te6edf3image_bytesTb4b4b4: Tffa657bytesTb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""SHA-256 hex digest of raw sticker bytes; used for deduplication."""
Tff7b72return Te6edf3hashlibTff7b72.Td2a8ffsha256Tb4b4b4(Te6edf3image_bytesTb4b4b4)Tff7b72.Td2a8ffhexdigestTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffdetect_image_format_from_magicTb4b4b4(Te6edf3image_bytesTb4b4b4: Tffa657bytesTb4b4b4) Tff7b72-Tff7b72> Tffa657str Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Detect a sticker payload format from its magic bytes.
Recognises PNG, JPEG, GIF, WebP, BMP, gzipped TGS (Lottie), and EBML/WebM
containers. Returns a normalized type key or None for unknown input.
"""
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3image_bytesTb4b4b4, Tb4b4b4(Tffa657bytesTb4b4b4, Tffa657bytearrayTb4b4b4)Tb4b4b4) Tff7b72or Tffa657lenTb4b4b4(Te6edf3image_bytesTb4b4b4) Tff7b72< T79c0ff4Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3b Tff7b72= Tffa657bytesTb4b4b4(Te6edf3image_bytesTb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3bTb4b4b4) Tff7b72>Tff7b72= T79c0ff8 Tff7b72and Te6edf3bTb4b4b4[Tb4b4b4:T79c0ff8Tb4b4b4] Tff7b72== Ta5d6ffbTa5d6ff"Tffea00\x89Ta5d6ffPNGTffea00\rTffea00\nTffea00\x1aTffea00\nTa5d6ff"Tb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffpngTa5d6ff"
Tff7b72if Tffa657lenTb4b4b4(Te6edf3bTb4b4b4) Tff7b72>Tff7b72= T79c0ff3 Tff7b72and Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4:T79c0ff3Tb4b4b4] Tff7b72== Ta5d6ffbTa5d6ff"Tffea00\xffTffea00\xd8Tffea00\xffTa5d6ff"Tb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffjpegTa5d6ff"
Tff7b72if Tffa657lenTb4b4b4(Te6edf3bTb4b4b4) Tff7b72>Tff7b72= T79c0ff6 Tff7b72and Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4:T79c0ff6Tb4b4b4] Tff7b72in Tb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffGIF87aTa5d6ff"Tb4b4b4, Ta5d6ffbTa5d6ff"Ta5d6ffGIF89aTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffgifTa5d6ff"
Tff7b72if Tffa657lenTb4b4b4(Te6edf3bTb4b4b4) Tff7b72>Tff7b72= T79c0ff12 Tff7b72and Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4:T79c0ff4Tb4b4b4] Tff7b72== Ta5d6ffbTa5d6ff"Ta5d6ffRIFFTa5d6ff" Tff7b72and Te6edf3bTb4b4b4[T79c0ff8Tb4b4b4:T79c0ff12Tb4b4b4] Tff7b72== Ta5d6ffbTa5d6ff"Ta5d6ffWEBPTa5d6ff"Tb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffwebpTa5d6ff"
Tff7b72if Tffa657lenTb4b4b4(Te6edf3bTb4b4b4) Tff7b72>Tff7b72= T79c0ff2 Tff7b72and Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4:T79c0ff2Tb4b4b4] Tff7b72== Ta5d6ffbTa5d6ff"Ta5d6ffBMTa5d6ff"Tb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffbmpTa5d6ff"
Tff7b72if Tffa657lenTb4b4b4(Te6edf3bTb4b4b4) Tff7b72>Tff7b72= T79c0ff4 Tff7b72and Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4:T79c0ff4Tb4b4b4] Tff7b72== Ta5d6ffbTa5d6ff"Tffea00\x1aTffea00\x45Tffea00\xdfTffea00\xa3Ta5d6ff"Tb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffwebmTa5d6ff"
Tff7b72if Tffa657lenTb4b4b4(Te6edf3bTb4b4b4) Tff7b72>Tff7b72= T79c0ff2 Tff7b72and Te6edf3bTb4b4b4[T79c0ff0Tb4b4b4:T79c0ff2Tb4b4b4] Tff7b72== Ta5d6ffbTa5d6ff"Tffea00\x1fTffea00\x8bTa5d6ff"Tb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6fftgsTa5d6ff"
Tff7b72return Tff7b72None
Tff7b72def Td2a8ff_read_png_dimensionsTb4b4b4(Te6edf3dataTb4b4b4: Tffa657bytesTb4b4b4) Tff7b72-Tff7b72> Tffa657tupleTb4b4b4[Tffa657intTb4b4b4, Tffa657intTb4b4b4] Tff7b72| Tff7b72NoneTb4b4b4:
Tff7b72if Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72< T79c0ff24 Tff7b72or Te6edf3dataTb4b4b4[T79c0ff12Tb4b4b4:T79c0ff16Tb4b4b4] Tff7b72!= Ta5d6ffbTa5d6ff"Ta5d6ffIHDRTa5d6ff"Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Te6edf3widthTb4b4b4, Te6edf3height Tff7b72= Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff"Ta5d6ff>IITa5d6ff"Tb4b4b4, Te6edf3dataTb4b4b4[T79c0ff16Tb4b4b4:T79c0ff24Tb4b4b4]Tb4b4b4)
Tff7b72return Tffa657intTb4b4b4(Te6edf3widthTb4b4b4)Tb4b4b4, Tffa657intTb4b4b4(Te6edf3heightTb4b4b4)
Tff7b72except Te6edf3structTff7b72.Td2a8fferrorTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72def Td2a8ff_read_webp_dimensionsTb4b4b4(Te6edf3dataTb4b4b4: Tffa657bytesTb4b4b4) Tff7b72-Tff7b72> Tffa657tupleTb4b4b4[Tffa657intTb4b4b4, Tffa657intTb4b4b4] Tff7b72| Tff7b72NoneTb4b4b4:
Tff7b72if Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72< T79c0ff30Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3chunk Tff7b72= Te6edf3dataTb4b4b4[T79c0ff12Tb4b4b4:T79c0ff16Tb4b4b4]
Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3chunk Tff7b72== Ta5d6ffbTa5d6ff"Ta5d6ffVP8 Ta5d6ff"Tb4b4b4:
Te6edf3w Tff7b72= Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff"Ta5d6ff<HTa5d6ff"Tb4b4b4, Te6edf3dataTb4b4b4[T79c0ff26Tb4b4b4:T79c0ff28Tb4b4b4]Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4] Tff7b72& T79c0ff0x3FFF
Te6edf3h Tff7b72= Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff"Ta5d6ff<HTa5d6ff"Tb4b4b4, Te6edf3dataTb4b4b4[T79c0ff28Tb4b4b4:T79c0ff30Tb4b4b4]Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4] Tff7b72& T79c0ff0x3FFF
Tff7b72return Tffa657intTb4b4b4(Te6edf3wTb4b4b4)Tb4b4b4, Tffa657intTb4b4b4(Te6edf3hTb4b4b4)
Tff7b72if Te6edf3chunk Tff7b72== Ta5d6ffbTa5d6ff"Ta5d6ffVP8LTa5d6ff"Tb4b4b4:
Te6edf3b1Tb4b4b4, Te6edf3b2Tb4b4b4, Te6edf3b3Tb4b4b4, Te6edf3b4 Tff7b72= Te6edf3dataTb4b4b4[T79c0ff21Tb4b4b4]Tb4b4b4, Te6edf3dataTb4b4b4[T79c0ff22Tb4b4b4]Tb4b4b4, Te6edf3dataTb4b4b4[T79c0ff23Tb4b4b4]Tb4b4b4, Te6edf3dataTb4b4b4[T79c0ff24Tb4b4b4]
Te6edf3w Tff7b72= Tb4b4b4(Tb4b4b4(Te6edf3b2 Tff7b72& T79c0ff0x3FTb4b4b4) Tff7b72<< T79c0ff8 Tff7b72| Te6edf3b1Tb4b4b4) Tff7b72+ T79c0ff1
Te6edf3h Tff7b72= Tb4b4b4(Tb4b4b4(Te6edf3b4 Tff7b72& T79c0ff0x0FTb4b4b4) Tff7b72<< T79c0ff10 Tff7b72| Te6edf3b3 Tff7b72<< T79c0ff2 Tff7b72| Tb4b4b4(Te6edf3b2 Tff7b72& T79c0ff0xC0Tb4b4b4) Tff7b72>> T79c0ff6Tb4b4b4) Tff7b72+ T79c0ff1
Tff7b72return Tffa657intTb4b4b4(Te6edf3wTb4b4b4)Tb4b4b4, Tffa657intTb4b4b4(Te6edf3hTb4b4b4)
Tff7b72if Te6edf3chunk Tff7b72== Ta5d6ffbTa5d6ff"Ta5d6ffVP8XTa5d6ff"Tb4b4b4:
Te6edf3w Tff7b72= Tb4b4b4(Te6edf3dataTb4b4b4[T79c0ff24Tb4b4b4] Tff7b72| Te6edf3dataTb4b4b4[T79c0ff25Tb4b4b4] Tff7b72<< T79c0ff8 Tff7b72| Te6edf3dataTb4b4b4[T79c0ff26Tb4b4b4] Tff7b72<< T79c0ff16Tb4b4b4) Tff7b72+ T79c0ff1
Te6edf3h Tff7b72= Tb4b4b4(Te6edf3dataTb4b4b4[T79c0ff27Tb4b4b4] Tff7b72| Te6edf3dataTb4b4b4[T79c0ff28Tb4b4b4] Tff7b72<< T79c0ff8 Tff7b72| Te6edf3dataTb4b4b4[T79c0ff29Tb4b4b4] Tff7b72<< T79c0ff16Tb4b4b4) Tff7b72+ T79c0ff1
Tff7b72return Tffa657intTb4b4b4(Te6edf3wTb4b4b4)Tb4b4b4, Tffa657intTb4b4b4(Te6edf3hTb4b4b4)
Tff7b72except Tb4b4b4(Tf85149IndexErrorTb4b4b4, Te6edf3structTff7b72.Td2a8fferrorTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72return Tff7b72None
Tff7b72def Td2a8ff_read_gif_dimensionsTb4b4b4(Te6edf3dataTb4b4b4: Tffa657bytesTb4b4b4) Tff7b72-Tff7b72> Tffa657tupleTb4b4b4[Tffa657intTb4b4b4, Tffa657intTb4b4b4] Tff7b72| Tff7b72NoneTb4b4b4:
Tff7b72if Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72< T79c0ff10Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Te6edf3wTb4b4b4, Te6edf3h Tff7b72= Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff"Ta5d6ff<HHTa5d6ff"Tb4b4b4, Te6edf3dataTb4b4b4[T79c0ff6Tb4b4b4:T79c0ff10Tb4b4b4]Tb4b4b4)
Tff7b72return Tffa657intTb4b4b4(Te6edf3wTb4b4b4)Tb4b4b4, Tffa657intTb4b4b4(Te6edf3hTb4b4b4)
Tff7b72except Te6edf3structTff7b72.Td2a8fferrorTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72def Td2a8ff_read_bmp_dimensionsTb4b4b4(Te6edf3dataTb4b4b4: Tffa657bytesTb4b4b4) Tff7b72-Tff7b72> Tffa657tupleTb4b4b4[Tffa657intTb4b4b4, Tffa657intTb4b4b4] Tff7b72| Tff7b72NoneTb4b4b4:
Tff7b72if Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72< T79c0ff26Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Te6edf3wTb4b4b4, Te6edf3h Tff7b72= Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff"Ta5d6ff<iiTa5d6ff"Tb4b4b4, Te6edf3dataTb4b4b4[T79c0ff18Tb4b4b4:T79c0ff26Tb4b4b4]Tb4b4b4)
Tff7b72return Tffa657intTb4b4b4(Tffa657absTb4b4b4(Te6edf3wTb4b4b4)Tb4b4b4)Tb4b4b4, Tffa657intTb4b4b4(Tffa657absTb4b4b4(Te6edf3hTb4b4b4)Tb4b4b4)
Tff7b72except Te6edf3structTff7b72.Td2a8fferrorTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72def Td2a8ffdetect_image_dimensionsTb4b4b4(Te6edf3image_typeTb4b4b4: Tffa657strTb4b4b4, Te6edf3dataTb4b4b4: Tffa657bytesTb4b4b4) Tff7b72-Tff7b72> Tffa657tupleTb4b4b4[Tffa657intTb4b4b4, Tffa657intTb4b4b4] Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Return (width, height) for a static sticker payload, or None.
Works for PNG, WebP (lossy/lossless/extended), GIF, and BMP without any
third-party imaging dependency.
"""
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3dataTb4b4b4, Tb4b4b4(Tffa657bytesTb4b4b4, Tffa657bytearrayTb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3raw Tff7b72= Tffa657bytesTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72if Te6edf3image_type Tff7b72== Ta5d6ff"Ta5d6ffpngTa5d6ff"Tb4b4b4:
Tff7b72return Te6edf3_read_png_dimensionsTb4b4b4(Te6edf3rawTb4b4b4)
Tff7b72if Te6edf3image_type Tff7b72== Ta5d6ff"Ta5d6ffwebpTa5d6ff"Tb4b4b4:
Tff7b72return Te6edf3_read_webp_dimensionsTb4b4b4(Te6edf3rawTb4b4b4)
Tff7b72if Te6edf3image_type Tff7b72== Ta5d6ff"Ta5d6ffgifTa5d6ff"Tb4b4b4:
Tff7b72return Te6edf3_read_gif_dimensionsTb4b4b4(Te6edf3rawTb4b4b4)
Tff7b72if Te6edf3image_type Tff7b72== Ta5d6ff"Ta5d6ffbmpTa5d6ff"Tb4b4b4:
Tff7b72return Te6edf3_read_bmp_dimensionsTb4b4b4(Te6edf3rawTb4b4b4)
Tff7b72if Te6edf3image_type Tff7b72== Ta5d6ff"Ta5d6ffjpegTa5d6ff"Tb4b4b4:
Tff7b72return Te6edf3_read_jpeg_dimensionsTb4b4b4(Te6edf3rawTb4b4b4)
Tff7b72return Tff7b72None
Tff7b72def Td2a8ff_read_jpeg_dimensionsTb4b4b4(Te6edf3dataTb4b4b4: Tffa657bytesTb4b4b4) Tff7b72-Tff7b72> Tffa657tupleTb4b4b4[Tffa657intTb4b4b4, Tffa657intTb4b4b4] Tff7b72| Tff7b72NoneTb4b4b4:
Te6edf3i Tff7b72= T79c0ff2
Te6edf3n Tff7b72= Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72while Te6edf3i Tff7b72+ T79c0ff9 Tff7b72< Te6edf3nTb4b4b4:
Tff7b72if Te6edf3dataTb4b4b4[Te6edf3iTb4b4b4] Tff7b72!= T79c0ff0xFFTb4b4b4:
Te6edf3i Tff7b72+Tff7b72= T79c0ff1
Tff7b72continue
Te6edf3marker Tff7b72= Te6edf3dataTb4b4b4[Te6edf3i Tff7b72+ T79c0ff1Tb4b4b4]
Te6edf3i Tff7b72+Tff7b72= T79c0ff2
Tff7b72if Te6edf3marker Tff7b72in Tb4b4b4(T79c0ff0xD8Tb4b4b4, T79c0ff0xD9Tb4b4b4)Tb4b4b4:
Tff7b72continue
Tff7b72if T79c0ff0xD0 Tff7b72<Tff7b72= Te6edf3marker Tff7b72<Tff7b72= T79c0ff0xD7Tb4b4b4:
Tff7b72continue
Tff7b72if Te6edf3i Tff7b72+ T79c0ff2 Tff7b72> Te6edf3nTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3seg_len Tff7b72= Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff"Ta5d6ff>HTa5d6ff"Tb4b4b4, Te6edf3dataTb4b4b4[Te6edf3i Tb4b4b4: Te6edf3i Tff7b72+ T79c0ff2Tb4b4b4]Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72if Te6edf3seg_len Tff7b72< T79c0ff2 Tff7b72or Te6edf3i Tff7b72+ Te6edf3seg_len Tff7b72> Te6edf3nTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if T79c0ff0xC0 Tff7b72<Tff7b72= Te6edf3marker Tff7b72<Tff7b72= T79c0ff0xCF Tff7b72and Te6edf3marker Tff7b72not Tff7b72in Tb4b4b4(T79c0ff0xC4Tb4b4b4, T79c0ff0xC8Tb4b4b4, T79c0ff0xCCTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3i Tff7b72+ T79c0ff7 Tff7b72> Te6edf3nTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Te6edf3hTb4b4b4, Te6edf3w Tff7b72= Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff"Ta5d6ff>HHTa5d6ff"Tb4b4b4, Te6edf3dataTb4b4b4[Te6edf3i Tff7b72+ T79c0ff3 Tb4b4b4: Te6edf3i Tff7b72+ T79c0ff7Tb4b4b4]Tb4b4b4)
Tff7b72return Tffa657intTb4b4b4(Te6edf3wTb4b4b4)Tb4b4b4, Tffa657intTb4b4b4(Te6edf3hTb4b4b4)
Tff7b72except Te6edf3structTff7b72.Td2a8fferrorTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3i Tff7b72+Tff7b72= Te6edf3seg_len
Tff7b72return Tff7b72None
Te6edf3MAX_TGS_DECOMPRESSED_BYTES Tff7b72= T79c0ff4 Tff7b72* T79c0ff1024 Tff7b72* T79c0ff1024
T8b949e# gzip-wrapped DEFLATE stream for zlib.decompressobj (16 + MAX_WBITS).
Te6edf3_GZIP_WBITS Tff7b72= T79c0ff31
Tff7b72def Td2a8ff_decompress_gzip_boundedTb4b4b4(Te6edf3dataTb4b4b4: Tffa657bytesTb4b4b4, Te6edf3max_bytesTb4b4b4: Tffa657intTb4b4b4) Tff7b72-Tff7b72> Tffa657bytesTb4b4b4:
T8b949e"""Decompress a gzip stream, never buffering more than max_bytes.
Unlike gzip.decompress (which expands the whole stream into memory
before any size check), this caps each decompression step so a small
"gzip bomb" cannot force an unbounded allocation. Raises ValueError
with invalid_tgs_too_large_decompressed once the output would exceed
max_bytes.
"""
Te6edf3decompressor Tff7b72= Te6edf3zlibTff7b72.Td2a8ffdecompressobjTb4b4b4(Te6edf3_GZIP_WBITSTb4b4b4)
Te6edf3chunksTb4b4b4: Tffa657listTb4b4b4[Tffa657bytesTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3total Tff7b72= T79c0ff0
Te6edf3remaining Tff7b72= Te6edf3data
Tff7b72while Tff7b72TrueTb4b4b4:
Te6edf3chunk Tff7b72= Te6edf3decompressorTff7b72.Td2a8ffdecompressTb4b4b4(Te6edf3remainingTb4b4b4, Te6edf3max_bytes Tff7b72- Te6edf3total Tff7b72+ T79c0ff1Tb4b4b4)
Tff7b72if Te6edf3chunkTb4b4b4:
Te6edf3chunksTff7b72.Td2a8ffappendTb4b4b4(Te6edf3chunkTb4b4b4)
Te6edf3total Tff7b72+Tff7b72= Tffa657lenTb4b4b4(Te6edf3chunkTb4b4b4)
Tff7b72if Te6edf3total Tff7b72> Te6edf3max_bytesTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_tgs_too_large_decompressedTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3remaining Tff7b72= Te6edf3decompressorTff7b72.Td2a8ffunconsumed_tail
Tff7b72if Tff7b72not Te6edf3remainingTb4b4b4:
Tff7b72break
Te6edf3tail Tff7b72= Te6edf3decompressorTff7b72.Td2a8ffflushTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3tailTb4b4b4:
Te6edf3total Tff7b72+Tff7b72= Tffa657lenTb4b4b4(Te6edf3tailTb4b4b4)
Tff7b72if Te6edf3total Tff7b72> Te6edf3max_bytesTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_tgs_too_large_decompressedTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3chunksTff7b72.Td2a8ffappendTb4b4b4(Te6edf3tailTb4b4b4)
Tff7b72return Ta5d6ffbTa5d6ff"Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3chunksTb4b4b4)
Tff7b72def Td2a8ffparse_tgsTb4b4b4(Te6edf3dataTb4b4b4: Tffa657bytesTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4:
T8b949e"""Decompress a TGS payload and parse the Lottie JSON inside.
Returns a dict with width, height, fps, duration_ms and the
raw lottie data. Raises ValueError if the file is not a valid
Lottie animation.
"""
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3dataTb4b4b4, Tb4b4b4(Tffa657bytesTb4b4b4, Tffa657bytearrayTb4b4b4)Tb4b4b4) Tff7b72or Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72< T79c0ff2Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_tgsTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3decompressed Tff7b72= Te6edf3_decompress_gzip_boundedTb4b4b4(
Tffa657bytesTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4,
Te6edf3MAX_TGS_DECOMPRESSED_BYTESTb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149ValueErrorTb4b4b4:
Tff7b72raise
Tff7b72except Tb4b4b4(Tf85149OSErrorTb4b4b4, Tf85149EOFErrorTb4b4b4, Te6edf3zlibTff7b72.Td2a8fferrorTb4b4b4, Te6edf3gzipTff7b72.Td2a8ffBadGzipFileTb4b4b4) Tff7b72as Te6edf3excTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_tgs_gzipTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4) Tff7b72from T7ee787exc
Tff7b72tryTb4b4b4:
Te6edf3lottie Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3decompressedTb4b4b4)
Tff7b72except Tb4b4b4(Tf85149ValueErrorTb4b4b4, Te6edf3jsonTff7b72.Td2a8ffJSONDecodeErrorTb4b4b4) Tff7b72as Te6edf3excTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_tgs_jsonTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4) Tff7b72from T7ee787exc
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3lottieTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_tgs_rootTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3width Tff7b72= Tffa657intTb4b4b4(Te6edf3lottieTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4) Tff7b72or T79c0ff0Tb4b4b4)
Te6edf3height Tff7b72= Tffa657intTb4b4b4(Te6edf3lottieTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhTa5d6ff"Tb4b4b4) Tff7b72or T79c0ff0Tb4b4b4)
Te6edf3fps Tff7b72= Tffa657floatTb4b4b4(Te6edf3lottieTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffrTa5d6ff"Tb4b4b4) Tff7b72or T79c0ff0Tb4b4b4)
Te6edf3in_point Tff7b72= Tffa657floatTb4b4b4(Te6edf3lottieTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffipTa5d6ff"Tb4b4b4) Tff7b72or T79c0ff0Tb4b4b4)
Te6edf3out_point Tff7b72= Tffa657floatTb4b4b4(Te6edf3lottieTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffopTa5d6ff"Tb4b4b4) Tff7b72or T79c0ff0Tb4b4b4)
Tff7b72except Tb4b4b4(Tf85149TypeErrorTb4b4b4, Tf85149ValueErrorTb4b4b4) Tff7b72as Te6edf3excTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_tgs_metadataTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4) Tff7b72from T7ee787exc
Tff7b72if Te6edf3width Tff7b72<Tff7b72= T79c0ff0 Tff7b72or Te6edf3height Tff7b72<Tff7b72= T79c0ff0 Tff7b72or Te6edf3fps Tff7b72<Tff7b72= T79c0ff0 Tff7b72or Te6edf3out_point Tff7b72<Tff7b72= Te6edf3in_pointTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_tgs_metadataTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3duration_ms Tff7b72= Tffa657roundTb4b4b4(Tb4b4b4(Tb4b4b4(Te6edf3out_point Tff7b72- Te6edf3in_pointTb4b4b4) Tff7b72/ Te6edf3fpsTb4b4b4) Tff7b72* T79c0ff1000.0Tb4b4b4)
Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffwidthTa5d6ff"Tb4b4b4: Te6edf3widthTb4b4b4,
Ta5d6ff"Ta5d6ffheightTa5d6ff"Tb4b4b4: Te6edf3heightTb4b4b4,
Ta5d6ff"Ta5d6fffpsTa5d6ff"Tb4b4b4: Te6edf3fpsTb4b4b4,
Ta5d6ff"Ta5d6ffduration_msTa5d6ff"Tb4b4b4: Te6edf3duration_msTb4b4b4,
Ta5d6ff"Ta5d6fflottieTa5d6ff"Tb4b4b4: Te6edf3lottieTb4b4b4,
Tb4b4b4}
Tff7b72def Td2a8ff_ebml_read_vintTb4b4b4(
Te6edf3bufTb4b4b4: Tffa657bytesTb4b4b4,
Te6edf3posTb4b4b4: Tffa657intTb4b4b4,
Tff7b72*Tb4b4b4,
Te6edf3mask_markerTb4b4b4: Tffa657bool Tff7b72= Tff7b72TrueTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657tupleTb4b4b4[Tffa657intTb4b4b4, Tffa657intTb4b4b4] Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Read an EBML variable-length integer at pos; returns (value, next_pos)."""
Tff7b72if Te6edf3pos Tff7b72>Tff7b72= Tffa657lenTb4b4b4(Te6edf3bufTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3first Tff7b72= Te6edf3bufTb4b4b4[Te6edf3posTb4b4b4]
Tff7b72if Te6edf3first Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3length Tff7b72= T79c0ff1
Te6edf3mask Tff7b72= T79c0ff0x80
Tff7b72while Te6edf3length Tff7b72<Tff7b72= T79c0ff8 Tff7b72and Tff7b72not Tb4b4b4(Te6edf3first Tff7b72& Te6edf3maskTb4b4b4)Tb4b4b4:
Te6edf3length Tff7b72+Tff7b72= T79c0ff1
Te6edf3mask Tff7b72>>Tff7b72= T79c0ff1
Tff7b72if Te6edf3length Tff7b72> T79c0ff8 Tff7b72or Te6edf3pos Tff7b72+ Te6edf3length Tff7b72> Tffa657lenTb4b4b4(Te6edf3bufTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3value Tff7b72= Te6edf3first Tff7b72& Tb4b4b4(Te6edf3mask Tff7b72- T79c0ff1Tb4b4b4) Tff7b72if Te6edf3mask_marker Tff7b72else Te6edf3first
Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(T79c0ff1Tb4b4b4, Te6edf3lengthTb4b4b4)Tb4b4b4:
Te6edf3value Tff7b72= Tb4b4b4(Te6edf3value Tff7b72<< T79c0ff8Tb4b4b4) Tff7b72| Te6edf3bufTb4b4b4[Te6edf3pos Tff7b72+ Te6edf3iTb4b4b4]
Tff7b72return Te6edf3valueTb4b4b4, Te6edf3pos Tff7b72+ Te6edf3length
Tff7b72def Td2a8ff_ebml_iter_elementsTb4b4b4(Te6edf3bufTb4b4b4: Tffa657bytesTb4b4b4, Te6edf3startTb4b4b4: Tffa657intTb4b4b4, Te6edf3endTb4b4b4: Tffa657intTb4b4b4)Tb4b4b4:
Te6edf3pos Tff7b72= Te6edf3start
Tff7b72while Te6edf3pos Tff7b72< Te6edf3endTb4b4b4:
Te6edf3id_res Tff7b72= Te6edf3_ebml_read_vintTb4b4b4(Te6edf3bufTb4b4b4, Te6edf3posTb4b4b4, Te6edf3mask_markerTff7b72=Tff7b72FalseTb4b4b4)
Tff7b72if Te6edf3id_res Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return
Te6edf3elem_idTb4b4b4, Te6edf3after_id Tff7b72= Te6edf3id_res
Te6edf3size_res Tff7b72= Te6edf3_ebml_read_vintTb4b4b4(Te6edf3bufTb4b4b4, Te6edf3after_idTb4b4b4)
Tff7b72if Te6edf3size_res Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return
Te6edf3sizeTb4b4b4, Te6edf3after_size Tff7b72= Te6edf3size_res
Te6edf3body_end Tff7b72= Tffa657minTb4b4b4(Te6edf3after_size Tff7b72+ Te6edf3sizeTb4b4b4, Te6edf3endTb4b4b4)
Tff7b72yield Te6edf3elem_idTb4b4b4, Te6edf3after_sizeTb4b4b4, Te6edf3body_end
Te6edf3pos Tff7b72= Te6edf3body_end
Tff7b72def Td2a8ff_ebml_read_uintTb4b4b4(Te6edf3bufTb4b4b4: Tffa657bytesTb4b4b4, Te6edf3startTb4b4b4: Tffa657intTb4b4b4, Te6edf3endTb4b4b4: Tffa657intTb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
Te6edf3val Tff7b72= T79c0ff0
Tff7b72for Te6edf3b Tff7b72in Te6edf3bufTb4b4b4[Te6edf3startTb4b4b4:Te6edf3endTb4b4b4]Tb4b4b4:
Te6edf3val Tff7b72= Tb4b4b4(Te6edf3val Tff7b72<< T79c0ff8Tb4b4b4) Tff7b72| Te6edf3b
Tff7b72return Te6edf3val
Tff7b72def Td2a8ff_ebml_read_floatTb4b4b4(Te6edf3bufTb4b4b4: Tffa657bytesTb4b4b4, Te6edf3startTb4b4b4: Tffa657intTb4b4b4, Te6edf3endTb4b4b4: Tffa657intTb4b4b4) Tff7b72-Tff7b72> Tffa657float Tff7b72| Tff7b72NoneTb4b4b4:
Te6edf3size Tff7b72= Te6edf3end Tff7b72- Te6edf3start
Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3size Tff7b72== T79c0ff4Tb4b4b4:
Tff7b72return Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff"Ta5d6ff>fTa5d6ff"Tb4b4b4, Te6edf3bufTb4b4b4[Te6edf3startTb4b4b4:Te6edf3endTb4b4b4]Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72if Te6edf3size Tff7b72== T79c0ff8Tb4b4b4:
Tff7b72return Te6edf3structTff7b72.Td2a8ffunpackTb4b4b4(Ta5d6ff"Ta5d6ff>dTa5d6ff"Tb4b4b4, Te6edf3bufTb4b4b4[Te6edf3startTb4b4b4:Te6edf3endTb4b4b4]Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72except Te6edf3structTff7b72.Td2a8fferrorTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72return Tff7b72None
Tff7b72def Td2a8ffparse_webmTb4b4b4(Te6edf3dataTb4b4b4: Tffa657bytesTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4:
T8b949e"""Parse a WebM container header to extract sticker-relevant metadata.
Returns width, height, fps (best-effort), duration_ms, the
detected video codec_id and has_audio flag. Raises ValueError
when the container is not a valid WebM file.
"""
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3dataTb4b4b4, Tb4b4b4(Tffa657bytesTb4b4b4, Tffa657bytearrayTb4b4b4)Tb4b4b4) Tff7b72or Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72< T79c0ff32Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_webmTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3raw Tff7b72= Tffa657bytesTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72if Te6edf3rawTb4b4b4[T79c0ff0Tb4b4b4:T79c0ff4Tb4b4b4] Tff7b72!= Ta5d6ffbTa5d6ff"Tffea00\x1aTffea00\x45Tffea00\xdfTffea00\xa3Ta5d6ff"Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_webm_headerTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3width Tff7b72= T79c0ff0
Te6edf3height Tff7b72= T79c0ff0
Te6edf3duration_ms Tff7b72= T79c0ff0
Te6edf3timecode_scale Tff7b72= T79c0ff1_000_000
Te6edf3duration_ticks Tff7b72= T79c0ff0.0
Te6edf3codec_id Tff7b72= Ta5d6ff"Ta5d6ff"
Te6edf3has_audio Tff7b72= Tff7b72False
Te6edf3track_default_duration_nsTb4b4b4: Tffa657listTb4b4b4[Tffa657intTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3elem_idTb4b4b4, Te6edf3body_startTb4b4b4, Te6edf3body_end Tff7b72in Te6edf3_ebml_iter_elementsTb4b4b4(Te6edf3rawTb4b4b4, T79c0ff0Tb4b4b4, Tffa657lenTb4b4b4(Te6edf3rawTb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3elem_id Tff7b72== T79c0ff0x18538067Tb4b4b4:
Tff7b72for Te6edf3seg_idTb4b4b4, Te6edf3sbTb4b4b4, Te6edf3se Tff7b72in Te6edf3_ebml_iter_elementsTb4b4b4(Te6edf3rawTb4b4b4, Te6edf3body_startTb4b4b4, Te6edf3body_endTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3seg_id Tff7b72== T79c0ff0x1654AE6BTb4b4b4:
Tff7b72for Te6edf3tr_idTb4b4b4, Te6edf3tbTb4b4b4, Te6edf3te Tff7b72in Te6edf3_ebml_iter_elementsTb4b4b4(Te6edf3rawTb4b4b4, Te6edf3sbTb4b4b4, Te6edf3seTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3tr_id Tff7b72== T79c0ff0xAETb4b4b4:
Te6edf3track_codec Tff7b72= Ta5d6ff"Ta5d6ff"
Te6edf3track_type Tff7b72= T79c0ff0
Te6edf3track_def_dur Tff7b72= T79c0ff0
Te6edf3t_w Tff7b72= Te6edf3t_h Tff7b72= T79c0ff0
Tff7b72for Te6edf3f_idTb4b4b4, Te6edf3fbTb4b4b4, Te6edf3fe Tff7b72in Te6edf3_ebml_iter_elementsTb4b4b4(Te6edf3rawTb4b4b4, Te6edf3tbTb4b4b4, Te6edf3teTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3f_id Tff7b72== T79c0ff0x83Tb4b4b4:
Te6edf3track_type Tff7b72= Te6edf3_ebml_read_uintTb4b4b4(Te6edf3rawTb4b4b4, Te6edf3fbTb4b4b4, Te6edf3feTb4b4b4)
Tff7b72elif Te6edf3f_id Tff7b72== T79c0ff0x86Tb4b4b4:
Te6edf3track_codec Tff7b72= Te6edf3rawTb4b4b4[Te6edf3fbTb4b4b4:Te6edf3feTb4b4b4]Tff7b72.Td2a8ffdecodeTb4b4b4(
Ta5d6ff"Ta5d6ffasciiTa5d6ff"Tb4b4b4,
Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffreplaceTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72elif Te6edf3f_id Tff7b72== T79c0ff0x23E383Tb4b4b4:
Te6edf3track_def_dur Tff7b72= Te6edf3_ebml_read_uintTb4b4b4(Te6edf3rawTb4b4b4, Te6edf3fbTb4b4b4, Te6edf3feTb4b4b4)
Tff7b72elif Te6edf3f_id Tff7b72== T79c0ff0xE0Tb4b4b4:
Tff7b72for Te6edf3v_idTb4b4b4, Te6edf3vbTb4b4b4, Te6edf3ve Tff7b72in Te6edf3_ebml_iter_elementsTb4b4b4(
Te6edf3rawTb4b4b4,
Te6edf3fbTb4b4b4,
Te6edf3feTb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3v_id Tff7b72== T79c0ff0xB0Tb4b4b4:
Te6edf3t_w Tff7b72= Te6edf3_ebml_read_uintTb4b4b4(Te6edf3rawTb4b4b4, Te6edf3vbTb4b4b4, Te6edf3veTb4b4b4)
Tff7b72elif Te6edf3v_id Tff7b72== T79c0ff0xBATb4b4b4:
Te6edf3t_h Tff7b72= Te6edf3_ebml_read_uintTb4b4b4(Te6edf3rawTb4b4b4, Te6edf3vbTb4b4b4, Te6edf3veTb4b4b4)
Tff7b72if Te6edf3track_type Tff7b72== T79c0ff1Tb4b4b4:
Te6edf3width Tff7b72= Te6edf3t_w Tff7b72or Te6edf3width
Te6edf3height Tff7b72= Te6edf3t_h Tff7b72or Te6edf3height
Te6edf3codec_id Tff7b72= Te6edf3track_codec Tff7b72or Te6edf3codec_id
Tff7b72if Te6edf3track_def_durTb4b4b4:
Te6edf3track_default_duration_nsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3track_def_durTb4b4b4)
Tff7b72elif Te6edf3track_type Tff7b72== T79c0ff2Tb4b4b4:
Te6edf3has_audio Tff7b72= Tff7b72True
Tff7b72elif Te6edf3seg_id Tff7b72== T79c0ff0x1549A966Tb4b4b4:
Tff7b72for Te6edf3inf_idTb4b4b4, Te6edf3ibTb4b4b4, Te6edf3ie Tff7b72in Te6edf3_ebml_iter_elementsTb4b4b4(Te6edf3rawTb4b4b4, Te6edf3sbTb4b4b4, Te6edf3seTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3inf_id Tff7b72== T79c0ff0x2AD7B1Tb4b4b4:
Te6edf3timecode_scale Tff7b72= Tb4b4b4(
Te6edf3_ebml_read_uintTb4b4b4(Te6edf3rawTb4b4b4, Te6edf3ibTb4b4b4, Te6edf3ieTb4b4b4) Tff7b72or Te6edf3timecode_scale
Tb4b4b4)
Tff7b72elif Te6edf3inf_id Tff7b72== T79c0ff0x4489Tb4b4b4:
Te6edf3d Tff7b72= Te6edf3_ebml_read_floatTb4b4b4(Te6edf3rawTb4b4b4, Te6edf3ibTb4b4b4, Te6edf3ieTb4b4b4)
Tff7b72if Te6edf3d Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3duration_ticks Tff7b72= Te6edf3d
Tff7b72if Te6edf3width Tff7b72<Tff7b72= T79c0ff0 Tff7b72or Te6edf3height Tff7b72<Tff7b72= T79c0ff0Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_webm_no_videoTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72if Te6edf3duration_ticks Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3duration_ms Tff7b72= Tffa657roundTb4b4b4(Te6edf3duration_ticks Tff7b72* Te6edf3timecode_scale Tff7b72/ T79c0ff1_000_000.0Tb4b4b4)
Te6edf3fps Tff7b72= T79c0ff0.0
Tff7b72if Te6edf3track_default_duration_nsTb4b4b4:
Te6edf3fps Tff7b72= T79c0ff1_000_000_000.0 Tff7b72/ Tffa657floatTb4b4b4(Te6edf3track_default_duration_nsTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)
Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffwidthTa5d6ff"Tb4b4b4: Tffa657intTb4b4b4(Te6edf3widthTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffheightTa5d6ff"Tb4b4b4: Tffa657intTb4b4b4(Te6edf3heightTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffduration_msTa5d6ff"Tb4b4b4: Tffa657intTb4b4b4(Te6edf3duration_msTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6fffpsTa5d6ff"Tb4b4b4: Te6edf3fpsTb4b4b4,
Ta5d6ff"Ta5d6ffcodec_idTa5d6ff"Tb4b4b4: Te6edf3codec_idTb4b4b4,
Ta5d6ff"Ta5d6ffhas_audioTa5d6ff"Tb4b4b4: Te6edf3has_audioTb4b4b4,
Tb4b4b4}
Tff7b72def Td2a8ff_validate_dimensions_telegram_staticTb4b4b4(Te6edf3widthTb4b4b4: Tffa657intTb4b4b4, Te6edf3heightTb4b4b4: Tffa657intTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72if Te6edf3width Tff7b72<Tff7b72= T79c0ff0 Tff7b72or Te6edf3height Tff7b72<Tff7b72= T79c0ff0Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_dimensionsTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72if Te6edf3width Tff7b72> Te6edf3STICKER_CANVAS Tff7b72or Te6edf3height Tff7b72> Te6edf3STICKER_CANVASTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffdimensions_too_largeTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72if Te6edf3STICKER_CANVAS Tff7b72not Tff7b72in Tb4b4b4(Te6edf3widthTb4b4b4, Te6edf3heightTb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffdimensions_not_512_on_one_sideTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72def Td2a8ffvalidate_sticker_payloadTb4b4b4(
Te6edf3image_bytesTb4b4b4: Tffa657bytesTb4b4b4,
Te6edf3image_typeTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4,
Tff7b72*Tb4b4b4,
Te6edf3strictTb4b4b4: Tffa657bool Tff7b72= Tff7b72FalseTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657tupleTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
T8b949e"""Validate a sticker payload against the legacy or strict Telegram rules.
When strict is False the validator preserves the historical behaviour
of the MeshChatX library (PNG/JPEG/GIF/WebP/BMP up to 512 KB, no dimension
enforcement). When strict is True the validator additionally enforces
Telegram-aligned size, dimension, FPS and duration limits per format.
Returns (normalized_image_type, content_hash_hex). Raises ValueError
with a short machine-readable reason on invalid input.
"""
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3image_bytesTb4b4b4, Tb4b4b4(Tffa657bytesTb4b4b4, Tffa657bytearrayTb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_image_bytesTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3image_bytesTb4b4b4) Tff7b72== T79c0ff0Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffempty_imageTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3nt Tff7b72= Te6edf3normalize_image_typeTb4b4b4(Te6edf3image_typeTb4b4b4)
Tff7b72if Tff7b72not Te6edf3ntTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_image_typeTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3detected Tff7b72= Te6edf3detect_image_format_from_magicTb4b4b4(Te6edf3image_bytesTb4b4b4)
Tff7b72if Tff7b72not Te6edf3detectedTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_image_signatureTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72if Te6edf3detected Tff7b72!= Te6edf3ntTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffmagic_type_mismatchTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3raw Tff7b72= Tffa657bytesTb4b4b4(Te6edf3image_bytesTb4b4b4)
Tff7b72if Tff7b72not Te6edf3strictTb4b4b4:
Tff7b72if Te6edf3nt Tff7b72not Tff7b72in Te6edf3_LEGACY_TYPESTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_image_typeTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3rawTb4b4b4) Tff7b72> Te6edf3MAX_STATIC_BYTESTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffimage_too_largeTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3_validate_strict_payloadTb4b4b4(Te6edf3ntTb4b4b4, Te6edf3rawTb4b4b4)
Tff7b72return Te6edf3detectedTb4b4b4, Te6edf3content_hash_hexTb4b4b4(Te6edf3rawTb4b4b4)
Tff7b72def Td2a8ff_validate_strict_payloadTb4b4b4(Te6edf3ntTb4b4b4: Tffa657strTb4b4b4, Te6edf3rawTb4b4b4: Tffa657bytesTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72if Te6edf3nt Tff7b72== Ta5d6ff"Ta5d6fftgsTa5d6ff"Tb4b4b4:
Tff7b72if Tffa657lenTb4b4b4(Te6edf3rawTb4b4b4) Tff7b72> Te6edf3MAX_ANIMATED_BYTESTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffanimated_too_largeTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3meta Tff7b72= Te6edf3parse_tgsTb4b4b4(Te6edf3rawTb4b4b4)
Tff7b72if Te6edf3metaTb4b4b4[Ta5d6ff"Ta5d6ffwidthTa5d6ff"Tb4b4b4] Tff7b72!= Te6edf3STICKER_CANVAS Tff7b72or Te6edf3metaTb4b4b4[Ta5d6ff"Ta5d6ffheightTa5d6ff"Tb4b4b4] Tff7b72!= Te6edf3STICKER_CANVASTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffanimated_dimensions_invalidTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72if Tff7b72not Tb4b4b4(Te6edf3ANIMATED_FPS_MIN Tff7b72<Tff7b72= Te6edf3metaTb4b4b4[Ta5d6ff"Ta5d6fffpsTa5d6ff"Tb4b4b4] Tff7b72<Tff7b72= Te6edf3ANIMATED_FPS_MAXTb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffanimated_fps_out_of_rangeTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72if Te6edf3metaTb4b4b4[Ta5d6ff"Ta5d6ffduration_msTa5d6ff"Tb4b4b4] Tff7b72> Te6edf3MAX_DURATION_MSTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffanimated_duration_too_longTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72return
Tff7b72if Te6edf3nt Tff7b72== Ta5d6ff"Ta5d6ffwebmTa5d6ff"Tb4b4b4:
Tff7b72if Tffa657lenTb4b4b4(Te6edf3rawTb4b4b4) Tff7b72> Te6edf3MAX_VIDEO_BYTESTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffvideo_too_largeTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3meta Tff7b72= Te6edf3parse_webmTb4b4b4(Te6edf3rawTb4b4b4)
Tff7b72if Te6edf3metaTb4b4b4[Ta5d6ff"Ta5d6ffhas_audioTa5d6ff"Tb4b4b4]Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffvideo_has_audioTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3codec Tff7b72= Tb4b4b4(Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffcodec_idTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffupperTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3codec Tff7b72and Ta5d6ff"Ta5d6ffVP9Ta5d6ff" Tff7b72not Tff7b72in Te6edf3codec Tff7b72and Ta5d6ff"Ta5d6ffV_VP9Ta5d6ff" Tff7b72not Tff7b72in Te6edf3codecTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffvideo_codec_not_vp9Ta5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3_validate_dimensions_telegram_staticTb4b4b4(Te6edf3metaTb4b4b4[Ta5d6ff"Ta5d6ffwidthTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3metaTb4b4b4[Ta5d6ff"Ta5d6ffheightTa5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72if Te6edf3metaTb4b4b4[Ta5d6ff"Ta5d6fffpsTa5d6ff"Tb4b4b4] Tff7b72and Te6edf3metaTb4b4b4[Ta5d6ff"Ta5d6fffpsTa5d6ff"Tb4b4b4] Tff7b72> Te6edf3VIDEO_FPS_MAX Tff7b72+ T79c0ff0.5Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffvideo_fps_too_highTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72if Te6edf3metaTb4b4b4[Ta5d6ff"Ta5d6ffduration_msTa5d6ff"Tb4b4b4] Tff7b72> Te6edf3MAX_DURATION_MSTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffvideo_duration_too_longTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72return
Tff7b72if Te6edf3nt Tff7b72in Te6edf3_TELEGRAM_STATIC_TYPESTb4b4b4:
Tff7b72if Tffa657lenTb4b4b4(Te6edf3rawTb4b4b4) Tff7b72> Te6edf3MAX_STATIC_BYTESTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffstatic_too_largeTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3dims Tff7b72= Te6edf3detect_image_dimensionsTb4b4b4(Te6edf3ntTb4b4b4, Te6edf3rawTb4b4b4)
Tff7b72if Te6edf3dims Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffstatic_dimensions_unknownTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3_validate_dimensions_telegram_staticTb4b4b4(Tff7b72*Te6edf3dimsTb4b4b4)
Tff7b72return
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffstrict_format_not_supportedTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72def Td2a8ffextract_metadataTb4b4b4(Te6edf3image_typeTb4b4b4: Tffa657strTb4b4b4, Te6edf3rawTb4b4b4: Tffa657bytesTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4:
T8b949e"""Best-effort extraction of width/height/fps/duration_ms for storage."""
Te6edf3nt Tff7b72= Te6edf3normalize_image_typeTb4b4b4(Te6edf3image_typeTb4b4b4) Tff7b72or Te6edf3image_type
Te6edf3out Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffwidthTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffheightTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6fffpsTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffduration_msTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffis_animatedTa5d6ff"Tb4b4b4: Te6edf3nt Tff7b72== Ta5d6ff"Ta5d6fftgsTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffis_videoTa5d6ff"Tb4b4b4: Te6edf3nt Tff7b72== Ta5d6ff"Ta5d6ffwebmTa5d6ff"Tb4b4b4,
Tb4b4b4}
Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3nt Tff7b72== Ta5d6ff"Ta5d6fftgsTa5d6ff"Tb4b4b4:
Te6edf3m Tff7b72= Te6edf3parse_tgsTb4b4b4(Te6edf3rawTb4b4b4)
Te6edf3outTff7b72.Td2a8ffupdateTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffwidthTa5d6ff"Tb4b4b4: Te6edf3mTb4b4b4[Ta5d6ff"Ta5d6ffwidthTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffheightTa5d6ff"Tb4b4b4: Te6edf3mTb4b4b4[Ta5d6ff"Ta5d6ffheightTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6fffpsTa5d6ff"Tb4b4b4: Te6edf3mTb4b4b4[Ta5d6ff"Ta5d6fffpsTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffduration_msTa5d6ff"Tb4b4b4: Te6edf3mTb4b4b4[Ta5d6ff"Ta5d6ffduration_msTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72elif Te6edf3nt Tff7b72== Ta5d6ff"Ta5d6ffwebmTa5d6ff"Tb4b4b4:
Te6edf3m Tff7b72= Te6edf3parse_webmTb4b4b4(Te6edf3rawTb4b4b4)
Te6edf3outTff7b72.Td2a8ffupdateTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffwidthTa5d6ff"Tb4b4b4: Te6edf3mTb4b4b4[Ta5d6ff"Ta5d6ffwidthTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffheightTa5d6ff"Tb4b4b4: Te6edf3mTb4b4b4[Ta5d6ff"Ta5d6ffheightTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6fffpsTa5d6ff"Tb4b4b4: Te6edf3mTb4b4b4[Ta5d6ff"Ta5d6fffpsTa5d6ff"Tb4b4b4] Tff7b72or Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffduration_msTa5d6ff"Tb4b4b4: Te6edf3mTb4b4b4[Ta5d6ff"Ta5d6ffduration_msTa5d6ff"Tb4b4b4] Tff7b72or Tff7b72NoneTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3dims Tff7b72= Te6edf3detect_image_dimensionsTb4b4b4(Te6edf3ntTb4b4b4, Te6edf3rawTb4b4b4)
Tff7b72if Te6edf3dims Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3outTb4b4b4[Ta5d6ff"Ta5d6ffwidthTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3outTb4b4b4[Ta5d6ff"Ta5d6ffheightTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3dims
Tff7b72except Tf85149ValueErrorTb4b4b4:
Tff7b72pass
Tff7b72return Te6edf3out
Te6edf3_EXPORT_FORMAT Tff7b72= Ta5d6ff"Ta5d6ffmeshchatx-stickersTa5d6ff"
Te6edf3_EXPORT_VERSION Tff7b72= T79c0ff1
Tff7b72def Td2a8ffvalidate_export_documentTb4b4b4(Te6edf3dataTb4b4b4: Tffa657objectTb4b4b4) Tff7b72-Tff7b72> Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4:
T8b949e"""Parse and validate a single-sticker export JSON document.
Each sticker dict has name, image_type, image_bytes (base64),
optional source_message_hash, and optional emoji (sticker tag).
"""
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3dataTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_documentTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72if Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffformatTa5d6ff"Tb4b4b4) Tff7b72!= Te6edf3_EXPORT_FORMATTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_formatTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3ver Tff7b72= Tffa657intTb4b4b4(Te6edf3dataTb4b4b4[Ta5d6ff"Ta5d6ffversionTa5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72except Tb4b4b4(Tf85149KeyErrorTb4b4b4, Tf85149TypeErrorTb4b4b4, Tf85149ValueErrorTb4b4b4) Tff7b72as Te6edf3excTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffunsupported_versionTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4) Tff7b72from T7ee787exc
Tff7b72if Te6edf3ver Tff7b72!= Te6edf3_EXPORT_VERSIONTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffunsupported_versionTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3stickers Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstickersTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3stickersTb4b4b4, Tffa657listTb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_stickers_arrayTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3outTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3iTb4b4b4, Te6edf3item Tff7b72in Tffa657enumerateTb4b4b4(Te6edf3stickersTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3itemTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffinvalid_sticker_at_Tffd700{Te6edf3iTffd700}Ta5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3name Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4)
Te6edf3image_type Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffimage_typeTa5d6ff"Tb4b4b4)
Te6edf3image_b64 Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffimage_bytesTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3image_b64Tb4b4b4, Tffa657strTb4b4b4) Tff7b72or Tff7b72not Te6edf3image_b64Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffmissing_image_bytes_at_Tffd700{Te6edf3iTffd700}Ta5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3base64Tff7b72.Td2a8ffb64decodeTb4b4b4(Te6edf3image_b64Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3validateTff7b72=Tff7b72FalseTb4b4b4)
Tff7b72except Tb4b4b4(Tf85149ValueErrorTb4b4b4, Tf85149TypeErrorTb4b4b4) Tff7b72as Te6edf3excTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffinvalid_base64_at_Tffd700{Te6edf3iTffd700}Ta5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4) Tff7b72from T7ee787exc
Te6edf3src Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsource_message_hashTa5d6ff"Tb4b4b4)
Te6edf3emoji Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffemojiTa5d6ff"Tb4b4b4)
Te6edf3outTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3name Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3nameTb4b4b4, Tffa657strTb4b4b4) Tff7b72else Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffimage_typeTa5d6ff"Tb4b4b4: Te6edf3image_typeTb4b4b4,
Ta5d6ff"Ta5d6ffimage_bytes_b64Ta5d6ff"Tb4b4b4: Te6edf3image_b64Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffsource_message_hashTa5d6ff"Tb4b4b4: Te6edf3src Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3srcTb4b4b4, Tffa657strTb4b4b4) Tff7b72else Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffemojiTa5d6ff"Tb4b4b4: Te6edf3emoji Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3emojiTb4b4b4, Tffa657strTb4b4b4) Tff7b72else Tff7b72NoneTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3out
Tff7b72def Td2a8ffbuild_export_documentTb4b4b4(Te6edf3stickersTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4, Te6edf3exported_at_isoTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4:
T8b949e"""Build a meshchatx-stickers JSON document for individual stickers."""
Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffformatTa5d6ff"Tb4b4b4: Te6edf3_EXPORT_FORMATTb4b4b4,
Ta5d6ff"Ta5d6ffversionTa5d6ff"Tb4b4b4: Te6edf3_EXPORT_VERSIONTb4b4b4,
Ta5d6ff"Ta5d6ffexported_atTa5d6ff"Tb4b4b4: Te6edf3exported_at_isoTb4b4b4,
Ta5d6ff"Ta5d6ffstickersTa5d6ff"Tb4b4b4: Te6edf3stickersTb4b4b4,
Tb4b4b4}
Tff7b72def Td2a8ffmime_for_image_typeTb4b4b4(Te6edf3normalized_typeTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""Return the HTTP Content-Type for a normalized sticker type key."""
Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffjpegTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffimage/jpegTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffpngTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffimage/pngTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffgifTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffimage/gifTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffwebpTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffimage/webpTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffbmpTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffimage/bmpTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fftgsTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffapplication/x-tgstickerTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffwebmTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffvideo/webmTa5d6ff"Tb4b4b4,
Tb4b4b4}Tff7b72.Td2a8ffgetTb4b4b4(Te6edf3normalized_typeTb4b4b4, Ta5d6ff"Ta5d6ffapplication/octet-streamTa5d6ff"Tb4b4b4)
Tff7b72def Td2a8ffsanitize_sticker_nameTb4b4b4(Te6edf3nameTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tffa657str Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Trim, strip non-printable characters, and clamp a sticker name to 128 chars."""
Tff7b72if Te6edf3name Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3s Tff7b72= Ta5d6ff"Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3ch Tff7b72for Te6edf3ch Tff7b72in Tffa657strTb4b4b4(Te6edf3nameTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4) Tff7b72if Te6edf3chTff7b72.Td2a8ffisprintableTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3sTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72return Te6edf3sTb4b4b4[Tb4b4b4:T79c0ff128Tb4b4b4]
Te6edf3_EMOJI_MAX_LEN Tff7b72= T79c0ff16
Tff7b72def Td2a8ffsanitize_sticker_emojiTb4b4b4(Te6edf3emojiTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tffa657str Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Allow up to a small number of characters for a sticker emoji tag.
The protocol does not enforce that stickers must carry an emoji (per user
decision); this helper only ensures the value is short, printable and
storable.
"""
Tff7b72if Te6edf3emoji Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3s Tff7b72= Tffa657strTb4b4b4(Te6edf3emojiTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3sTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3s Tff7b72= Ta5d6ff"Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3ch Tff7b72for Te6edf3ch Tff7b72in Te6edf3s Tff7b72if Te6edf3chTff7b72.Td2a8ffisprintableTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3sTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72return Te6edf3sTb4b4b4[Tb4b4b4:Te6edf3_EMOJI_MAX_LENTb4b4b4]
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────